<html>
<head>
<style type="text/css">
body, html {
    margin: 0;
    width: 100%;
    height: 100%;
}
#canvas {
    width: 100%;
    height: 100%;
}
</style>

<script type="text/javascript" src="qrc:/webvfx/scripts/shaderkit.js"></script>
<script type="text/javascript" src="qrc:/webvfx/scripts/easing.js"></script>

<script type="text/javascript">
function CrossZoom() {
    this.renderer = new ShaderKit.Renderer(document.getElementById("canvas"));
    this.shader = new ShaderKit.Shader(this.renderer,
                                       ShaderKit.Shader.loadShader("crossZoom"));

    // 0->1.0
    var strength = webvfx.getNumberParameter("Strength");

    // Mirrored sinusoidal loop. 0->strength then strength->0
    this.easeStrength = new WebVfx.Easing.Sinusoidal(0, strength, 0.5);
    this.easeDissolve = new WebVfx.Easing.Exponential(0, 1, 1);
    // Linear interpolate center across center half of the image
    this.easeCenter = new WebVfx.Easing.Linear(0.25, 0.5, 1);
}

CrossZoom.prototype.render = function (time) {
    var shader = this.shader;
    shader.updateUniform("sourceTex",
                         webvfx.getImage('sourceImage').toImageData());
    shader.updateUniform("targetTex",
                         webvfx.getImage('targetImage').toImageData());
    shader.updateUniform("strength", this.easeStrength.easeInOut(time));
    shader.updateUniform("dissolve", this.easeDissolve.easeInOut(time));
    shader.updateUniform("center", [this.easeCenter.ease(time), 0.5]);
    this.renderer.render(shader);
}

function init() {
    try {
        resize();
        var crossZoom = new CrossZoom();
        webvfx.renderRequested.connect(crossZoom, CrossZoom.prototype.render);
        webvfx.imageTypeMap = { "sourceImage" : webvfx.SourceImageType,
                                "targetImage" : webvfx.TargetImageType };
        webvfx.readyRender(true);
    } catch (e) {
        console.warn(e);
        webvfx.readyRender(false);
    }
}

function resize() {
    var canvas = document.getElementById("canvas");
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
}

window.addEventListener("load", init, false);
window.addEventListener("resize", resize, false);
</script>


<!-- Based on https://github.com/evanw/glfx.js/blob/master/src/filters/blur/zoomblur.js -->
<script id="crossZoom" type="x-shader/x-fragment">
precision mediump float;
varying vec2 texCoord;
uniform sampler2D sourceTex;
uniform sampler2D targetTex;
uniform float dissolve;
uniform float strength;
uniform vec2 center;

/* random number between 0 and 1 */
float random(in vec3 scale, in float seed) {
    /* use the fragment position for randomness */
    return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);
}

vec3 crossFade(in vec2 uv) {
    return mix(texture2D(sourceTex, uv).rgb,
               texture2D(targetTex, uv).rgb,
               dissolve);
}

void main() {
    vec3 color = vec3(0.0);
    float total = 0.0;
    vec2 toCenter = center - texCoord;

    /* randomize the lookup values to hide the fixed number of samples */
    float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);

    for (float t = 0.0; t <= 40.0; t++) {
        float percent = (t + offset) / 40.0;
        float weight = 4.0 * (percent - percent * percent);
        color += crossFade(texCoord + toCenter * percent * strength) * weight;
        total += weight;
    }
    gl_FragColor = vec4(color / total, 1.0);
}
</script>

</head>
<body>
    <canvas id="canvas"></canvas>
</body>
</html>
